<template>
  <div class="tree-table-wrap">
    <div v-if="config.showbtns" class="tool-bar">
      <el-button-group
        :style="{
          'min-width': '209px',
          'margin-bottom': ' 10px',
          width: config.buttonGroupWidth || '100%'
        }"
      >
        <el-button :icon="Refresh" type="primary" @click="getTreeData()"> 刷新 </el-button>
        <el-button type="primary" @click="setExpand">
          {{ toggleExpand ? "全部收起" : "全部展开" }}
        </el-button>

        <slot name="operate"></slot>
      </el-button-group>
    </div>
    <div v-if="config.search" class="search-wrap">
      <el-input v-model="filterText" :placeholder="config.placeholder || '输入关键字进行过滤'" />
    </div>
    <vxe-table
      :key="treeData"
      ref="xTree"
      v-loading="loading"
      border="none"
      :checkbox-config="{
        labelField: config.label || 'nodename',
        checkField: config.checkField || 'checked',
        checkStrictly: config.checkStrictly || false
      }"
      class="tree-table"
      :data="treeData"
      :max-height="config.maxHeight ?? ''"
      :row-config="{
        keyField: config.keyField || 'id',
        height: config.rowHeight || 32,
        isCurrent: true //当鼠标点击行时，是否要高亮当前行
      }"
      :show-header="false"
      show-overflow
      :tree-config="{
        rowField: config.keyField || 'id',
        line: config.line ?? false,
        iconOpen: config.line ? 'vxe-icon-square-minus' : '',
        iconClose: config.line ? 'vxe-icon-square-plus' : '',
        rowField: config.keyField || 'id',
        children: 'children',
        expandAll: expandAll,
        expandRowKeys: expandRowKeys,
        transform: config.config ?? true,
        // parentid: config.parentid || 'parentid'
        parentField: 'parentid'
      }"
      @cell-click="handleCellClick"
      @cell-dblclick="handleCellDbClick"
      @checkbox-change="handleSelectionChange"
    >
      <vxe-column v-if="config.type === 'checkbox'" tree-node type="checkbox" />

      <vxe-column v-else field="label" tree-node>
        <template #default="{ row }">
          <span :class="{ 'label-disabled': row.disabled }">
            {{ row.label }}
          </span>
        </template>
      </vxe-column>
    </vxe-table>
  </div>
</template>

<script>
import { postRequest, queryList } from "@/api/mains";
import { Refresh } from "@element-plus/icons-vue";

export default {
  name: "CommonVxeTableTree",
  props: {
    maxHeight: {
      type: Number,
      default: null
    },
    url: {
      type: String,
      default: ""
    },
    config: {
      type: Object,
      default: () => {}
    },
    queryForm: {
      type: Object,
      default: () => {}
    },
    data: {
      type: [Object, Array],
      default: () => []
    }
  },
  emits: {
    "on-change-nodes": null,
    "on-handle-cell-click": null,
    "on-handle-tree-id": null,
    "on-handl-db-cell-click": null,
    "on-get-tree-data": null
  },
  setup(props, { emit, expose }) {
    const xTree = ref();
    const treeData = ref([]);
    const templateTreeData = ref([]);
    const loading = ref(false);
    const filterText = ref();
    const expandRowKeys = ref([]);
    const expandAll = ref(props.config.expandAll ?? false);
    const toggleExpand = ref(expandAll.value);
    const keyField = computed(() => {
      return props.config.keyField || "id";
    });

    //获取数据
    const getExpandRowKeys = treeData => {
      for (const item of treeData) {
        if (item.children) {
          getExpandRowKeys(item.children);
          const isSomePermission = item.children.some(item => item.checked);
          if (isSomePermission) {
            expandRowKeys.value.push(item[keyField.value]);
          }
        }
        if (item.checked) {
          expandRowKeys.value.push(item[keyField.value]);
        }
      }
    };

    /**
     * 过滤树结构
     */
    const getFilterTreeData = () => {
      const arr = [];
      const key = props.config.nodename || "nodename";
      const { value } = templateTreeData;
      if (!value.length) return arr;
      function filterTree(data) {
        for (const item of data) {
          if (item[key].indexOf(filterText.value) > -1) {
            arr.push(item);
          }
          if (item.children && item.children.length) filterTree(item.children);
        }
      }

      filterTree(value);
      return arr;
    };

    const getTreeData = async queryForm => {
      // loading.value = true;
      const params = queryForm || props.queryForm;
      const { config } = props;
      toggleExpand.value = config.expandAll;
      let datas = [];
      if (!props.url) {
        datas = props.data;
      } else {
        const Fn = config.method === "post" ? queryList : postRequest;
        const res = await Fn(props.url, params);
        datas = res.data;
      }

      emit("on-get-tree-data", datas);
      loading.value = false;
      if (datas.rows) {
        if (datas.rows.constructor == Object) {
          treeData.value = [datas.rows];
          templateTreeData.value = [{ ...datas.rows }];
        } else {
          treeData.value = datas.rows;
          templateTreeData.value = [...datas.rows];
        }
      }

      if (config.isSelectRow) {
        handleCellClick({ row: treeData.value?.[0] });
      }
      if (config.expandRowKeys) {
        getExpandRowKeys(treeData.value);
      } else if (!config.isList) {
        expandRowKeys.value = treeData.value.map(item => item.id);
      } else {
        expandRowKeys.value = treeData.value.filter(item => item.parentid === "root");
      }
    };

    //为保证与CommonTreeMain组件公用，需定义handleRefreshTree方法刷新左边树的数据
    const handleRefreshTree = () => {
      getTreeData();
    };

    const setExpand = () => {
      toggleExpand.value = !toggleExpand.value;
      xTree.value.setAllTreeExpand(toggleExpand.value);
    };

    /**
     * 设置当前子元素跟当前元素保持一致
     */
    const setChildrenToParentStatus = ({ rowid, checked }) => {
      //获取当前元素的子元素
      let curItem = [];
      const getCurrenItem = data => {
        if (!data || !data.length) return curItem;
        for (const item of data) {
          if (item.id === rowid) {
            curItem = { ...item };
            return;
          } else {
            getCurrenItem(item.children);
          }
        }
      };

      getCurrenItem(treeData.value);

      //所有子元素保持一致
      const setChildren = data => {
        if (!data?.children || !data?.children.length) return;
        for (const item of data.children) {
          xTree.value.setCheckboxRow(item, checked);
          setChildren(item);
        }
      };

      const setParent = row => {
        const getParentRow = xTree.value.getParentRow(row);
        if (getParentRow) {
          xTree.value.setCheckboxRow(getParentRow, checked);
          setParent(getParentRow);
        }
      };

      setChildren(curItem);
      if (checked) {
        setParent(curItem);
      }
    };

    const handleSelectionChange = val => {
      const { records = [], rowid, checked } = val || {};
      if (props.config?.checkStrictlyExtra) {
        setChildrenToParentStatus({ rowid, checked });
        const selectNodes = xTree.value.getCheckboxRecords(true);
        emit("on-change-nodes", selectNodes);
        return;
      }
      emit("on-change-nodes", records);
    };

    const getCheckedKeys = () => {
      return xTree.value.getCheckboxRecords(true);
    };

    const handleCellClick = ({ row }) => {
      const key = props.config.keyField || "id";
      const parentRow = xTree.value.getParentRow(row);
      //在点击文字的时候并不会高亮，需要自行设置高亮
      xTree.value.clearCurrentRow();
      xTree.value.setCurrentRow(row);

      emit("on-handle-cell-click", row);
      emit("on-handle-tree-id", row?.[key], { row, parentRow });
    };

    const handleCellDbClick = row => {
      emit("on-handl-db-cell-click", row);
    };

    expose({ getCheckedKeys, getTreeData, handleRefreshTree });
    watch(
      () => props.url,
      () => {
        if (props.url) {
          getTreeData();
        }
      },
      {
        immediate: true
      }
    );

    watch(
      () => props.data,
      () => {
        if (!props.url) {
          getTreeData();
        }
      },
      {
        immediate: true,
        deep: true
      }
    );

    watch(
      () => props.config.expandAll,
      newVal => {
        expandAll.value = newVal;
        toggleExpand.value = newVal;
      }
    );

    watch(
      () => filterText.value,
      () => {
        treeData.value = getFilterTreeData();
      }
    );
    return {
      treeData,
      expandRowKeys,
      loading,
      xTree,
      expandAll,
      toggleExpand,
      filterText,
      handleSelectionChange,
      getTreeData,
      setExpand,
      handleCellClick,
      handleCellDbClick,
      Refresh
    };
  }
};
</script>
<style scoped lang="scss">
.tree-table-wrap {
  .tool-bar {
    width: 100%;
  }
  :deep() {
    .el-input {
      width: 100% !important;
      margin-bottom: 10px;
    }
    .el-button {
      & + .el-button {
        margin-left: 0;
      }
    }
    .vxe-tree-cell {
      cursor: pointer;
    }
    .el-button-group {
      display: flex;
      .el-button {
        flex: auto;
        padding: 8px 11.9px;
      }
    }
  }
  .label-disabled {
    color: #999999;
  }
}
</style>
